home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The Best of MacTutor - S…e Code for Volumes 1 to 5
/
The Best of MacTutor - Source Code for Volume 1-5 (Wayzata Technology)(6031)(1990).bin
/
Source Code
/
#41 (Feb 89)
/
window source
/
Window1.p
< prev
Wrap
Text File
|
1988-10-02
|
28KB
|
1,120 lines
(*
© 1988, Apple Computer, Inc.
All rights reserved.
Window1.p: A HyperCard XCMD in MPW Pascal 2.0.2 by Joe Zuffoletto
Version 1.0, 29 June 1988
Form: window title,top,left,bottom,right
Example: window "My Window",50,100,300,400
Notes: Window puts up a standard document window with scroll bars.
The window can be dragged, resized, zoomed, and closed.
Command-W is supported for closing the window. Command-spacebar
toggles the menubar on and off, as in HyperCard. If you
try to draw the window's title bar off the screen or under
the menubar, Window will abort with an error message. Error
messages can be examined by looking at HyperCard's global
variable "the result" after calling Window.
Window is MultiFinder friendly and works with HyperCard 1.2
or later. It supports multiple displays on the Mac II as well.
You must supply your own code for displaying whatever you
want to display in the window.
-----------------------------------------------------------------------------
To compile and link this file using MPW Pascal 2.0.2, select the following lines
and press ENTER:
Pascal Window1.p
link -o "Hard Disk":HyperCard:"HyperCard Stacks":Home ∂
-rt XCMD=2000 -sn Main=Window ∂
Window1.p.o {MPW}Libraries:Interface.o ∂
{MPW}PLibraries:PasLib.o ∂
-m ENTRYPOINT
Use other link files as necessary.
The above link directives install the XCMD resource into the Home stack. You
can substitute the name of any stack you want; be sure to provide the
correct pathname. Also, make sure the target stack already has a resource
fork or it won't work. You can create an empty resource fork in a stack
with ResEdit.
-----------------------------------------------------------------------------
*)
{$R-}
{$S Window}
UNIT DummyUnit;
INTERFACE
USES MemTypes,QuickDraw,OSIntf,ToolIntf,PasLibIntf,HyperXCmd;
PROCEDURE EntryPoint(paramPtr:XCmdPtr);
IMPLEMENTATION
TYPE Str31 = String[31];
OffScrHandle = ^OffScrRecPtr; {Attach to refCon of a window}
OffScrRecPtr = ^OffScrRecord;
OffScrRecord = RECORD
{Next month!}
END;
ScrollHandle = ^ScrollPtr; {Attach to refCon of a scroll bar}
ScrollPtr = ^ScrollRecord;
ScrollRecord = RECORD
{Next month!}
END;
PROCEDURE Window(paramPtr:XCmdPtr);FORWARD;
PROCEDURE EntryPoint(paramPtr:XCmdPtr);
BEGIN
Window(paramPtr);
END;
FUNCTION Min(int1,int2:INTEGER): INTEGER;
BEGIN
{Next month!}
END; {Min}
PROCEDURE InitBlit(theWindow:WindowPtr);
BEGIN
{Next month!}
END; {InitBlit}
PROCEDURE InvalContents(theWindow:WindowPtr;theOldSize:Rect);
BEGIN
{More to come next month!}
EraseRect(theWindow^.portRect);
InvalRect(theWindow^.portRect);
END; {InvalContents}
PROCEDURE DrawContents(theWindow:WindowPtr);
BEGIN
{Next month!}
END; {DrawContents}
PROCEDURE ScrollContents(theWindow:WindowPtr;dh,dv:INTEGER);
BEGIN
{Next month!}
END; {ScrollContents}
PROCEDURE MyScroll(theControl:ControlHandle;partCode:INTEGER);
BEGIN
{Next month!}
END; {MyScroll}
PROCEDURE Window(paramPtr:XCmdPtr);
CONST
minParamCount = 5;
smallestHeight = 100;
smallestWidth = 100;
_WaitNextEvent = $A860;
_Unimplemented = $A89F;
active = 0;
inactive = 255;
MouseMovedEvt = $FA;
SuspendResumeEvt = $01;
SuspendEventMask = $1;
ConvertScrapMask = $2;
browseTool = 6069;
HCWidth = 512;
HCHeight = 342;
padding = 16;
VAR
toolVis,patVis: BOOLEAN;
msgVis,fatVis: BOOLEAN;
hasWaitNextEvent: BOOLEAN;
inBackGround,smallScreen: BOOLEAN;
DoneFlag,HaveEvent: BOOLEAN;
menuWasHidden: BOOLEAN;
wTop,wLeft,wBottom,wRight: INTEGER;
partCode,controlCode: INTEGER;
largestHeight,largestWidth: INTEGER;
dummy,charCode: INTEGER;
screenWidth,screenHeight: INTEGER;
myDocWidth,myDocHeight: INTEGER;
eventPoint: Point;
wRect,screenRect,dragRect: Rect;
winSizeLimits: Rect;
oldSize: Rect;
newSize,dontCare: LONGINT;
envError: OSErr;
cursorRgn: RgnHandle;
hScroll,vScroll: ControlHandle;
whichControl: ControlHandle;
myWindow,whichWindow: WindowPtr;
fatBitsWindow: WindowPtr;
HCrefresh: Str31;
wT,wL,wB,wR,wTitle: Str255;
toolStr,patStr,msgStr: Str255;
widthStr,heightStr: Str255;
myBits: BitMap;
theEnv: SysEnvRec;
myEvent: EventRecord;
wRecord: WindowRecord;
HCPort: GrafPtr;
theOffScrHandle: OffScrHandle;
theScrollHandle: ScrollHandle;
myOffScr: OffScrRecord;
myScrollRecord: ScrollRecord;
FUNCTION TrapAvailable(tNumber: INTEGER; tType: TrapType):BOOLEAN;
{Check to see if a given trap is implemented.}
BEGIN
TrapAvailable := NGetTrapAddress(tNumber, tType) <> GetTrapAddress(_Unimplemented);
END; {TrapAvailable}
FUNCTION CreateHScrollBar(theWindow:WindowPtr;theValue,theMin,theMax:INTEGER;theRefCon:LONGINT):ControlHandle;
VAR
myWindowRect,hScrRect : Rect;
{Allocate and draw a horizontal scroll bar in theWindow.
Return a controlHandle to the scroll bar.}
BEGIN
SetPort(theWindow);
myWindowRect := theWindow^.portRect;
SetRect(hScrRect,myWindowRect.left -1,
myWindowRect.bottom - 15,
myWindowRect.right - 14,
myWindowRect.bottom + 1);
CreateHScrollBar := NewControl(theWindow,hScrRect,'MyHoriz',TRUE,
theValue,theMin,theMax,scrollBarProc,theRefCon);
END; {CreateHScrollBar}
FUNCTION CreateVScrollBar(theWindow:WindowPtr;theValue,theMin,theMax:INTEGER;theRefCon:LONGINT):ControlHandle;
VAR
myWindowRect,hScrRect : Rect;
{Allocate and draw a vertical scroll bar in theWindow.
Return a controlHandle to the scroll bar.}
BEGIN
SetPort(theWindow);
myWindowRect := theWindow^.portRect;
SetRect(hScrRect,myWindowRect.right -15,
myWindowRect.top - 1,
myWindowRect.right + 1,
myWindowRect.bottom - 14);
CreateVScrollBar := NewControl(theWindow,hScrRect,'MyVert',TRUE,
theValue,theMin,theMax,scrollBarProc,theRefCon);
END; {CreateVScrollBar}
PROCEDURE InvalScroll(theWindow:WindowPtr);
VAR
theRect,tallRect,wideRect : Rect;
{Accumulate the rectangles occupied by theWindow's
horizontal and vertical scroll bars into the update
region.}
BEGIN
SetPort(theWindow);
theRect := theWindow^.portRect;
ClipRect(theRect);
{ Accumulate tallRect, which is occupied by the vertical scroll bar }
SetRect(tallRect,theRect.right-15,
theRect.top,
theRect.right,
theRect.bottom);
EraseRect(tallRect);
InvalRect(tallRect);
{ Accumulate wideRect, which is occupied by the horizontal scroll bar }
SetRect(wideRect,theRect.left,
theRect.bottom-15,
theRect.right,
theRect.bottom);
EraseRect(wideRect);
InvalRect(wideRect);
END; {InvalScroll}
PROCEDURE Deactivate(theWindow:WindowPtr);
{Deactivate the scroll bars in theWindow in accordance
with the human interface guidelines. This means we must
erase everything enclosed by the control rectangles.}
VAR
theControl: ControlHandle;
theControlRect: Rect;
BEGIN
{I always title my scroll bars 'MyVert' and 'MyHoriz'
so I can easily find them by walking the window's
control list.}
theControl := WindowPeek(theWindow)^.controlList;
WHILE (theControl <> NIL) DO
BEGIN
IF (theControl^^.contrlTitle = 'MyVert') OR
(theControl^^.contrlTitle = 'MyHoriz') THEN
BEGIN
theControlRect := theControl^^.contrlRect;
InsetRect(theControlRect,1,1);
EraseRect(theControlRect);
END; {IF}
theControl := theControl^^.nextControl;
END; {WHILE}
END; {Deactivate}
PROCEDURE HiliteScrollBars(theWindow:WindowPtr);
{Reactivate the scroll bars; e.g., when we resume
under MultiFinder. More next month!}
BEGIN
HiliteControl(vScroll,INTEGER(active));
HiliteControl(hScroll,INTEGER(active));
END; {HiliteScrollBars}
PROCEDURE MoveScrollBars(theWindow:WindowPtr);
{Call this procedure after theWindow has changed size.
MoveScrollBars erases theWindow's scroll bars, resizes
them, and redraws them.}
VAR
myWindowRect: Rect;
vScrRect,hScrRect: Rect;
BEGIN
myWindowRect := theWindow^.portRect;
SetRect(hScrRect,myWindowRect.left - 1,
myWindowRect.bottom - 15,
myWindowRect.right - 14,
myWindowRect.bottom + 1);
SetRect(vScrRect,myWindowRect.right - 15,
myWindowRect.top - 1,
myWindowRect.right + 1,
myWindowRect.bottom - 14);
SetPort(theWindow);
ClipRect(myWindowRect);
{Hide and resize the scroll bars to fit the new window size.}
HideControl(hScroll);
HideControl(vScroll);
MoveControl(hScroll,hScrRect.left,hScrRect.top);
SizeControl(hScroll,(hScrRect.right - hScrRect.left),
(hScrRect.bottom - hScrRect.top));
MoveControl(vScroll,vScrRect.left,vScrRect.top);
SizeControl(vScroll,(vScrRect.right - vScrRect.left),
(vScrRect.bottom - vScrRect.top));
HiliteScrollBars(theWindow);
ShowControl(hScroll);
ShowControl(vScroll);
END; {MoveScrollBars}
PROCEDURE ScrollWithThumb(theControl:ControlHandle;theEventPoint:Point);
BEGIN
{Next month!}
END; {ScrollWithThumb}
FUNCTION WhichDevice(thePoint:Point):GDHandle;
{For machines that support color QuickDraw and
multiple screens, WhichDevice figures out which screen
thePoint is on and returns a GDHandle to that screen.
thePoint might be where the mouse was clicked, for
example. Thanks to Greg Marriott for this code.}
VAR
aDevice: GDHandle;
foundOne: BOOLEAN;
BEGIN
aDevice := GetDeviceList;
foundOne := FALSE;
{Walk the device list until thePoint is contained
in some device's screen rectangle.}
WHILE (aDevice <> NIL) AND NOT foundOne DO
BEGIN
IF PtInRect(thePoint,aDevice^^.gdRect) THEN
BEGIN
WhichDevice := aDevice;
foundOne := TRUE;
END;
aDevice := aDevice^^.gdNextGD;
END;
END; { WhichDevice }
FUNCTION MenuBarHeight: INTEGER;
{Returns the height of the menubar in pixels, as
read from the low memory global mBarHeight.}
CONST
mBarHeight = $BAA;
VAR
menuBarHeightPtr: ^INTEGER;
BEGIN
menuBarHeightPtr := Pointer(mBarHeight);
MenuBarHeight := menuBarHeightPtr^;
END; {MenuBarHeight}
FUNCTION OnAScreen(theRect:Rect):BOOLEAN;
{OnAScreen returns FALSE if all of a window's title
bar is off the screen or if any part of it is under
the menubar. The portRect of the window to be checked
should be passed in theRect.}
CONST
titleBarHeight = 18;
VAR
deskRgn: RgnHandle;
topLeft,topRight: Point;
BEGIN
deskRgn := GetGrayRgn;
topLeft.v := theRect.top - titleBarHeight;
topLeft.h := theRect.left + titleBarHeight;
topRight.v := topLeft.v;
topRight.h := theRect.right - titleBarHeight;
IF ((PtInRgn(topLeft,deskRgn)) OR (PtInRgn(topRight,deskRgn))) THEN
OnAScreen := TRUE
ELSE
OnAScreen := FALSE;
END; {OnAScreen}
PROCEDURE ZoomIt(theWindow:WindowPtr;partCode:INTEGER;clickedWhere:Point);
{ZoomIt supports more elegant window zooming on multiple
screen systems. theWindow will zoom to fill whatever
screen the zoom box was on when it was clicked. The
window state toggles between original size and zoomed
size, as usual. Thanks to Greg Marriott for this code.}
CONST
titleBarHeight = 18;
TYPE
WStatePtr = ^WStateData;
WStateHandle = ^WStatePtr;
VAR
oldRect,newRect: Rect;
maxHeight: INTEGER;
BEGIN
oldRect := theWindow^.portRect;
IF theEnv.hasColorQD THEN
BEGIN
newRect := WhichDevice(clickedWhere)^^.gdRect;
IF WhichDevice(clickedWhere) = GetMainDevice THEN
newRect.top := newRect.top + MenuBarHeight;
END
ELSE
newRect := GetGrayRgn^^.rgnBBox;
newRect.left := newRect.left + 2;
newRect.top := newRect.top + titleBarHeight + 2;
newRect.right := newRect.right - 3;
newRect.bottom := newRect.bottom - 3;
IF NOT EqualRect(oldRect,newRect) THEN
WITH WindowPeek(theWindow)^ DO
WStateHandle(dataHandle)^^.stdState := newRect;
SetPort(theWindow);
EraseRect(whichWindow^.portRect);
InvalRect(whichWindow^.portRect);
ZoomWindow(theWindow,partcode,FALSE);
END; { ZoomIt }
{$I XCmdGlue.inc}
PROCEDURE Fail(errStr:Str255);
{Fail returns errStr to HyperCard and exits the XCMD.
errStr can then be checked by inspecting HyperCard's
global variable "the result." See "XCMD's for Hyper-
Card" by Gary Bond (MIS Press, 1988) for more details.
© 1988 by Gary Bond
All rights reserved.
You may use this code for NON-COMMERCIAL purposes.}
BEGIN
paramPtr^.returnValue := PasToZero(errStr);
SysBeep(1);
EXIT(Window);
END; {Fail}
PROCEDURE CheckParamCount;
{CheckParamCount sees if the number of parameters
passed to the XCMD matches the number expected. If
not, we exit from the XCMD with an error message.
See "XCMD's for HyperCard" by Gary Bond (MIS Press,
1988) for more details.
© 1988 by Gary Bond
All rights reserved.
You may use this code for NON-COMMERCIAL purposes.}
VAR
numParams : INTEGER;
BEGIN
numParams := paramPtr^.paramCount;
IF(numParams <> minParamCount) THEN
Fail('Form: HyperWindow "Window Title",top,left,bottom,right');
END; {CheckParamCount}
FUNCTION GetHCVersion:Str255;
{Return a string containing the version of HyperCard
being used; e.g., '1.2'}
BEGIN
ZeroToPas(EvalExpr('the version')^,GetHCVersion);
END; {GetHCVersion}
PROCEDURE HideWindoids;
{Get and save the visible state of the tool, pattern,
message and fatbits windoids; then hide them if they
are showing.}
VAR
toolH,patH,msgH,fatH: Handle;
PROCEDURE HideFatBits;
{HyperCard does not have a built-in command for hiding
and showing the fatbits windoid, so we have to do it
ourselves. HideFatBits walks the window list until it
finds a window with title "FatBits," then hides it if
the visible field of its WindowRecord is true.
HideFatBits also saves the WindowPtr to the fatbits
windoid so we can use it later (e.g., to show the
windoid again).}
CONST
windowList = $9D6; {Low memory global location.}
VAR
theWindow: WindowPeek;
theWindowPtr: ^WindowPtr;
BEGIN
theWindowPtr := Pointer(windowList);
theWindow := WindowPeek(theWindowPtr^);
fatVis := FALSE;
WHILE (theWindow <> NIL) DO
BEGIN
IF (theWindow^.titleHandle^^ = 'FatBits') THEN
BEGIN
fatBitsWindow := WindowPtr(theWindow);
IF (theWindow^.visible = TRUE) THEN
BEGIN
fatVis := TRUE;
HideWindow(fatBitsWindow);
theWindow := NIL;
END;
END;
IF (theWindow <> NIL) THEN
theWindow := WindowPeek(theWindow)^.nextWindow;
END; {WHILE}
END; {HideFatBits}
BEGIN {HideWindoids}
{Get visible state of windoids.}
toolH := EvalExpr('visible of tool window');
ZeroToPas(toolH^,toolStr);
DisposHandle(toolH);
toolVis := StrToBool(toolStr);
patH := EvalExpr('visible of pattern window');
ZeroToPas(patH^,patStr);
DisposHandle(patH);
patVis := StrToBool(patStr);
msgH := EvalExpr('visible of message window');
ZeroToPas(msgH^,msgStr);
DisposHandle(msgH);
msgVis := StrToBool(msgStr);
{Hide the ones that are showing.}
HideFatBits;
IF toolVis THEN
SendHCMessage('hide tool window');
IF patVis THEN
SendHCMessage('hide pattern window');
IF msgVis THEN
SendHCMessage('hide message window');
END; {HideWindoids}
PROCEDURE ShowWindoids;
{This routine assumes HideWindoids has been called
before. ShowWindoids restores the visible state of
the windoids to that saved by HideWindoids.}
BEGIN
IF toolVis THEN
SendHCMessage('show tool window');
IF patVis THEN
SendHCMessage('show pattern window');
IF msgVis THEN
SendHCMessage('show message window');
{As in HideWindoids, we must take care of the FatBits
windoid ourselves.}
IF fatVis THEN
BEGIN
ShowWindow(fatBitsWindow);
SelectWindow(fatBitsWindow);
END;
END; {ShowWindoids}
PROCEDURE ToggleMenuBar;
{Set the visible of the menubar to not the visible of
the menubar.}
BEGIN
IF MenuBarHeight = 0 THEN
SendHCMessage('show menuBar')
ELSE
SendHCMessage('hide menuBar');
END; {ToggleMenuBar}
PROCEDURE GetHCBitMap;
BEGIN
{Next month!}
END; {GetHCBitMap}
PROCEDURE AdjustCursor;
{AdjustCursor changes cursorRgn to the region that contains
the cursor. As soon as the cursor moves out of cursorRgn, we
get an event and can change the cursor and cursorRgn again.
cursorRgn is either the content region of our window or
the region containing everything BUT the content region of our
window.}
VAR
mousePt: Point;
myWinContRect: Rect;
myWinContRgn: RgnHandle;
deskRgn: RgnHandle;
handHdl: CursHandle;
BEGIN
SetPort(myWindow);
GetMouse(mousePt);
LocalToGlobal(mousePt);
myWinContRgn := NewRgn;
{Calculate the "work region" of our window, which is its
content region minus the scroll bars and grow icon.
This is the region within which we want the cursor to
change to HyperCard's browse tool, and outside of which
we want it to be an arrow.}
WITH WindowPeek(myWindow)^.contRgn^^.rgnBBox DO
SetRect(myWinContRect,left, top, right - 15, bottom - 15);
RectRgn(myWinContRgn,myWinContRect);
IF PtInRect(mousePt,myWinContRect) THEN
BEGIN
{The cursor is in the work region of our window. Set to browse tool.}
handHdl := GetCursor(browseTool);
IF (handHdl <> NIL) THEN
SetCursor(handHdl^^)
ELSE
{Set to arrow if can't find browse tool resource.}
InitCursor;
{Set the cursor region equal to our window's work region.}
SetEmptyRgn(cursorRgn);
CopyRgn(myWinContRgn,cursorRgn);
END
ELSE
BEGIN
{The cursor is outside our window. Set to arrow.}
InitCursor;
{Get the current desktop region.}
deskRgn := GetGrayRgn;
{Set cursorRgn to the desktop region's bounding box. It is
important to add the menu bar area to cursorRgn too.}
SetRectRgn(cursorRgn, deskRgn^^.rgnBBox.left,
deskRgn^^.rgnBBox.top,
deskRgn^^.rgnBBox.right,
deskRgn^^.rgnBBox.bottom);
{Punch out our window's content region from the big region.}
DiffRgn(cursorRgn,myWinContRgn,cursorRgn);
END;
DisposeRgn(myWinContRgn);
END; {AdjustCursor}
BEGIN {Main Program}
{Check the HyperCard version. Must be 1.2 or greater.}
IF GetHCVersion < '1.2' THEN
Fail('Sorry, must have HyperCard 1.2 or greater.');
{Save thy grafPort upon entering!}
GetPort(HCPort);
{Check and reset our environment.}
CheckParamCount;
FlushEvents(everyEvent,0);
InitCursor;
{Find out what kind of machine we're running on.}
envError := SysEnvirons(1,theEnv);
IF (envError <> noErr) THEN
Fail('SysEnvirons call failed.');
{Convert HyperTalk input parameters for use here.}
ZeroToPas(paramPtr^.params[1]^,wTitle);
ZeroToPas(paramPtr^.params[2]^,wT);
ZeroToPas(paramPtr^.params[3]^,wL);
ZeroToPas(paramPtr^.params[4]^,wB);
ZeroToPas(paramPtr^.params[5]^,wR);
wTop := INTEGER(StrToNum(wT));
wLeft := INTEGER(StrToNum(wL));
wBottom := INTEGER(StrToNum(wB));
wRight := INTEGER(StrToNum(wR));
{If window size parameters are too small or illegal, set
the window to a predefined minimum size.}
IF ((wRight - wLeft) < smallestWidth) THEN
wRight := wLeft + smallestWidth;
IF ((wBottom - wTop) < smallestHeight) THEN
wBottom := wTop + smallestHeight;
{Make sure the user is not trying to draw the window off
the screen or under the menubar.}
SetRect(wRect,wLeft,wTop,wRight,wBottom);
IF NOT OnAScreen(wRect) THEN
Fail('You are trying to draw your window off the screen!');
{Get the bounds of the desktop.}
screenRect := GetGrayRgn^^.rgnBBox;
{If we have a small screen, make a note of it so we can hide the
card window during context switches under MultiFinder.}
ZeroToPas(EvalExpr('item 3 of the screenRect')^,widthStr);
screenWidth := INTEGER(StrToNum(widthStr));
ZeroToPas(EvalExpr('item 4 of the screenRect')^,heightStr);
screenHeight := INTEGER(StrToNum(heightStr));
IF (screenWidth = 512) AND (screenHeight = 342) THEN
smallScreen := TRUE
ELSE
smallScreen := FALSE;
HideWindoids;
IF MenuBarHeight > 0 THEN
menuWasHidden := FALSE
ELSE
menuWasHidden := TRUE;
{This is for scrolling and will be explained next month.}
theOffScrHandle := OffScrHandle(NewHandle(SizeOf(OffScrRecord)));
IF MemError <> noErr THEN
Fail('Out of memory. Buy more.');
myDocWidth := HCWidth + padding;
myDocHeight := HCHeight + padding;
WITH theOffScrHandle^^ DO
BEGIN
{Next month!}
END;
GetHCBitMap;
{Draw the window!}
myWindow := NewWindow(@wRecord,wRect,wTitle,TRUE,zoomDocProc,
WindowPtr(-1),TRUE,1);
IF (myWindow = NIL) THEN
BEGIN
ShowWindoids;
Fail('Not enough memory to draw window.');
END
ELSE
BEGIN
{This is for scrolling. Stay tuned....}
SetWRefCon(myWindow,LONGINT(theOffScrHandle));
InitBlit(myWindow);
DrawGrowIcon(myWindow);
theScrollHandle := ScrollHandle(NewHandle(SizeOf(ScrollRecord)));
IF MemError <> noErr THEN
Fail('Out of memory. Buy more.');
{Draw horizontal and vertical scroll bars in our
window.}
hScroll := CreateHScrollBar(myWindow,0,0,myDocWidth,LONGINT(theScrollHandle));
vScroll := CreateVScrollBar(myWindow,0,0,myDocHeight,LONGINT(theScrollHandle));
HiliteScrollBars(myWindow);
DrawContents(myWindow);
SetRect(dragRect,screenRect.left + 4,
screenRect.top,
screenRect.right - 4,
screenRect.bottom - 4);
largestHeight := screenRect.bottom - screenRect.top;
largestWidth := screenRect.right - screenRect.left;
SetRect(winSizeLimits,smallestWidth,
smallestHeight,
largestWidth,
largestHeight);
HCRefresh := 'Go to this card';
cursorRgn := NewRgn;
inBackGround := FALSE;
DoneFlag := FALSE;
REPEAT
{Call WaitNextEvent, if available. Otherwise call
GetNextEvent.}
IF hasWaitNextEvent THEN
HaveEvent := WaitNextEvent(everyEvent,myEvent,30,cursorRgn)
ELSE
BEGIN
HaveEvent := GetNextEvent(everyEvent,myEvent);
AdjustCursor;
END;
IF HaveEvent THEN
BEGIN
IF (myEvent.what = app4Evt) THEN
{Pre-process app4Evt's fed to us by MultiFinder.}
CASE BSR(myEvent.message,24) OF
MouseMovedEvt:
AdjustCursor;
SuspendResumeEvt:
BEGIN
myEvent.what := activateEvt;
{ Resume event }
IF (BAND(myEvent.message,SuspendEventMask) <> 0) THEN
inBackground := FALSE
ELSE
{ Suspend event }
inBackground := TRUE;
myEvent.message := LONGINT(myWindow);
END; {SuspendResumeEvt}
END; {CASE BSR}
END; {IF HaveEvent}
CASE myEvent.what OF
mouseDown:
BEGIN
partCode := FindWindow(myEvent.where,whichWindow);
IF (whichWindow = myWindow) THEN
BEGIN
{Deal with mouse hits to our window.}
CASE partCode OF
inDrag:
BEGIN
SelectWindow(whichWindow); {DragWindow bug}
DragWindow(whichWindow,myEvent.where,dragRect);
SendCardMessage(HCrefresh);
AdjustCursor;
END;
inGrow:
BEGIN
IF StillDown THEN {GrowWindow bug}
BEGIN
oldSize := whichWindow^.portRect;
newSize := GrowWindow(whichWindow,myEvent.where,winSizeLimits);
IF (newSize <> 0) THEN
BEGIN
InvalScroll(whichWindow);
SizeWindow(whichWindow,LOWORD(newSize),HIWORD(newSize),FALSE);
InvalContents(whichWindow,oldSize);
DrawGrowIcon(whichWindow);
MoveScrollBars(whichWindow);
END; {IF newSize}
END; {IF StillDown}
END; {inGrow}
inZoomIn,inZoomOut:
BEGIN
IF (TrackBox(whichWindow,myEvent.where,partCode)) THEN
BEGIN
InvalScroll(whichWindow);
ZoomIt(whichWindow,partCode,myEvent.where);
InvalContents(whichWindow,oldSize);
DrawGrowIcon(whichWindow);
MoveScrollBars(whichWindow);
END; {IF TrackBox}
END; {inZoomIn,inZoomOut}
inContent:
BEGIN
SetPort(whichWindow);
eventPoint := myEvent.where;
GlobalToLocal(eventPoint);
controlCode := FindControl(eventPoint,whichWindow,whichControl);
ClipRect(whichWindow^.portRect);
IF (controlCode = inThumb) THEN
ScrollWithThumb(whichControl,eventPoint)
ELSE IF (controlCode <> 0) THEN
dummy := TrackControl(whichControl,eventPoint,@MyScroll);
END; {inContent}
inGoAway:
BEGIN
IF(TrackGoAway(whichWindow,myEvent.where)) THEN
DoneFlag := TRUE;
END; {inGoAway}
END; {CASE partCode}
END
ELSE
BEGIN
IF MenuBarHeight > 0 THEN
BEGIN
FlashMenuBar(0);
Delay(LONGINT(6),dontCare);
FlashMenuBar(0);
END; {IF MenuBarHeight}
END; {IF FindWindow...ELSE}
END; {mouseDown}
activateEvt:
BEGIN
IF(WindowPtr(myEvent.message) = myWindow) THEN
BEGIN
SetPort(myWindow);
ClipRect(myWindow^.portRect);
DrawGrowIcon(myWindow);
IF inBackground THEN
BEGIN
{We've been sent behind another application
under MultiFinder, so deactivate the scroll
bars and show the menubar if it was hidden.}
Deactivate(myWindow);
IF smallScreen THEN
ShowHide(WindowPtr(HCPort),FALSE);
IF MenuBarHeight = 0 THEN
BEGIN
SendHCMessage('show menubar');
menuWasHidden := TRUE;
END
ELSE
menuWasHidden := FALSE;
END
ELSE
BEGIN
{We've been brought to the front under Multi-
Finder, so reactivate the scroll bars and
hide the menubar if it was hidden before.}
ShowHide(WindowPtr(HCPort),TRUE);
IF menuWasHidden THEN
SendHCMessage('hide menubar');
DrawControls(myWindow);
HiliteScrollBars(myWindow);
FlushEvents(everyEvent,0);
END; {IF inBackground}
END; {IF WindowPtr}
END; {activateEvt}
updateEvt:
BEGIN
{Handle updates to our window.}
IF(WindowPtr(myEvent.message) = myWindow) THEN
BEGIN
{Always do this stuff}
SetPort(myWindow);
BeginUpdate(myWindow);
ClipRect(myWindow^.portRect);
DrawGrowIcon(myWindow);
{Always do this stuff under single Finder but
only if in foreground under MultiFinder}
IF NOT inBackground THEN
BEGIN
HiliteScrollBars(myWindow);
DrawControls(myWindow);
AdjustCursor;
END;
{Always do this stuff}
DrawContents(myWindow);
EndUpdate(myWindow);
END {IF myEvent.message}
{Handle updates to HyperCard's card window.}
ELSE IF (WindowPtr(myEvent.message) = WindowPtr(HCPort)) THEN
BEGIN
SendHCMessage(HCRefresh);
{Must zero out card window's update region
ourselves because the SendHCMessage call
doesn't do it, and we'll wind up in an
infinite loop if we don't.}
BeginUpdate(WindowPtr(HCPort));
EndUpdate(WindowPtr(HCPort));
END; {IF... ELSE}
END; {updateEvt}
keyDown:
BEGIN
IF(BitAnd(myEvent.modifiers,cmdKey) <> 0) THEN
BEGIN
charCode := BitAnd(myEvent.message,charCodeMask);
{Pressing command-spacebar toggles the menubar.}
IF(CHR(charCode) = ' ') THEN
ToggleMenuBar
{Pressing command-W closes the window and exits
the XCMD.}
ELSE IF(CHR(charCode) = 'w') THEN
DoneFlag := True;
END;
END;
END; {CASE myEvent.what}
UNTIL (DoneFlag = True);
{Clean up and get outta here!}
DisposeRgn(cursorRgn);
DisposHandle(Handle(theOffScrHandle));
DisposHandle(Handle(theScrollHandle));
CloseWindow(myWindow);
SendCardMessage(HCrefresh);
ShowWindoids;
InitCursor;
FlushEvents(everyEvent,0);
{Restore thy grafPort}
SetPort(HCPort);
END; {IF myWindow...ELSE}
END; {Main}
END. {Window}